
#pragma once
#include "FMDBColumn.h"
#include <oci.h>
#include <vector>
#include <map>

//note: this is read only record set,if want to insert or update use another record set
class FMDBRecordSet
{

public:
	FMDBRecordSet(void);
	~FMDBRecordSet(void);

	void AddColumn(FMDBColumn *col,ub4 colIndex);
	void AddColumn(FMDBIOVColumn *col,ub4 colIndex);

	ColumnInfo *GetColumnInfo(ub4 colIndex);
	ColumnInfo *GetColumnInfo(CString colName);

	int GetRowStorageSize();//get one row storage size in byte

	//return columns' map,
	//todo_lei: these functions should be refactoring, it should return just one column by column ID or column name
	std::map<ub4,FMDBColumn*> *GetColumns(){return &m_ColumnMapByPos;}
	std::map<ub4,FMDBIOVColumn*> *GetIOVColumns(){return &m_IOVColumnMapByPos;}

	

	OCIStmt * GetStatementHandle() const { return m_pStmt; }
	void SetStatementHandle(OCIStmt * val,bool isRelease=true) { m_pStmt = val; m_bstmtRelease=isRelease;}

	int GetCacheSize(){return m_CacheSize;}
	void SetCacheSize(int val);//note:set cache size only affect exist columns, columns insert after this call will not allocate memory

	int First();//get first row
	int Next();//return next row

	//note:use Last() and GetCurrentRowNumber() can get row acount,but it may be need's long time to run
	int Last();//get last row
	int GetRowCount();//get total row count of recordset
	int GetColumnCount();//get column Count

	bool IsEmptyValue(int ColIndex);	//get if the column data is empty
	bool IsEmptyValue(CString ColName);	

	//note: the caller should know what data type will be returned and do not release the memory returned.
	void *GetValue(int ColIndex);	//get cell value of current row and ColIndex
	void *GetValue(CString ColName);	//get cell value of current row and ColName

	bool GetUInt64Value(int colIndex,unsigned __int64& val);		//get db id value from oci number
	bool GetUInt64Value(CString ColName, unsigned __int64& val);	//get db id value from oci number

	bool GetInt64Value(int colIndex,__int64& val);		//get db id value from oci number
	bool GetInt64Value(CString ColName, __int64& val);	//get db id value from oci number

	bool GetIntValue(int colIndex,int& val);
	bool GetIntValue(CString ColName,int& val);

	bool GetShortValue(int colIndex,short& val);
	bool GetShortValue(CString ColName,short& val);

	bool GetDoubleValue(int colIndex,double& val);
	bool GetDoubleValue(CString ColName,double& val);

	bool GetString(int colIndex,CString& val);
	bool GetString(CString ColName,CString& val);

	OCIError * GetErrorHandle() const { return m_pErr; }
	void SetErrorHandle(OCIError * val) { m_pErr = val; }

	bool IsScrollable() const { return m_bIsScrollable; }
	void IsScrollable(bool val) { m_bIsScrollable = val; }

	bool IsReady() const { return m_bIsready; }
	void IsReady(bool val) ;

	bool Auto() const { return m_bAuto; }
	void Auto(bool val) { m_bAuto = val; }

	void ResetIOVColumnValue();
private:
	

	std::map<ub4,ColumnInfo*> m_ColInfoMapByPos;		//map the column information by column position ID
	std::map<CString,ColumnInfo*> m_ColInfoMapByName;	//map the column information by column name

	//std::vector<FMDBColumn *> m_vColumn;		//stores the return schema
	//std::vector<FMDBIOVColumn *> m_vIOVColumn;	//stores the return schema

	std::map<ub4,FMDBColumn*> m_ColumnMapByPos;
	std::map<ub4,FMDBIOVColumn*> m_IOVColumnMapByPos;

	OCIStmt *m_pStmt;//statement handle for data fetch
	
	int m_CacheSize;//cache row size
	OCIError *m_pErr;

	//cursor position
	int m_CacheRowNumber;//indicate current row number from cache start row,1-base
	int m_CacheEndRowNumber;//indicate end row number in cache,in case of fetched row number smaller than cache

	bool m_bstmtRelease;//if need release stmt,because if stmt is allocate by ociAllocate function then cannot release by ocistmtrelease function
	bool m_bIsScrollable;//if this recordset is scrollable or non-scrollable
	bool m_bIsready;//if the recordset is ready to use	
	bool m_bAuto;//if the recordset automatically get columns and maintain storage
	int m_iColCount;//columns count, get from statement execution
	FMDBColumn **m_pColumns;	//columns pointer array
	FMDBIOVColumn **m_pIOVColumns;//iov columns pointer array
};

